package com.dmai.capacity.platform.oauth.controller;

import java.security.Principal;
import java.util.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.filter.config.ConfigTools;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.dmai.capacity.platform.common.constant.CommonConstant;
import com.dmai.capacity.platform.common.constant.SecurityConstants;
import com.dmai.capacity.platform.common.constant.UaaConstant;
import com.dmai.capacity.platform.common.dto.ResponseEntity;
import com.dmai.capacity.platform.common.exception.BusinessException;
import com.dmai.capacity.platform.common.model.BaseUser;
import com.dmai.capacity.platform.common.model.LoginAppUser;
import com.dmai.capacity.platform.common.properties.SecurityProperties;
import com.dmai.capacity.platform.common.utils.*;
import com.dmai.capacity.platform.constants.ExceptionEnum;
import com.dmai.capacity.platform.oauth.common.model.DefaultClientDetails;
import com.dmai.capacity.platform.oauth.common.service.IOauthClientService;
import com.dmai.capacity.platform.oauth.common.util.AuthUtils;
import com.dmai.capacity.platform.oauth.pojo.request.UserPasswordLoginRequest;
import com.dmai.capacity.platform.oauth.pojo.response.LoginResponse;
import com.dmai.capacity.platform.oauth.service.ISysTokenService;
import com.dmai.capacity.platform.oauth.service.impl.CustomTokenServices;
import com.dmai.capacity.platform.oauth.service.impl.RedisAuthorizationCodeServices;
import com.dmai.capacity.platform.oauth.service.impl.RedisClientDetailsService;
import com.dmai.capacity.platform.oauth.util.RsaTools;
import com.dmai.capacity.platform.oauth.utils.UsernameHolder;
import com.dmai.capacity.platform.user.pojo.response.InstitutionVO;
import com.dmai.capacity.platform.user.service.ISysInstitutionService;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import lombok.extern.slf4j.Slf4j;

import static com.dmai.capacity.platform.common.constant.CommonConstant.BEARER_TYPE;
import static com.dmai.capacity.platform.common.constant.SecurityConstants.AUTHORIZATION_CODE;


@Slf4j
@RestController
@SuppressWarnings("all")
public class OAuth2Controller {

    @Autowired
    private ISysTokenService sysTokenService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RedisAuthorizationCodeServices redisAuthorizationCodeService;
    private static OAuth2Request storedRequest;
    @Autowired
    private TokenStore tokenStore;
    @Lazy
    @Autowired
    private TokenEnhancer tokenEnhancer;
    @Resource
    private SecurityProperties securityProperties;
    @Resource
    private IOauthClientService clientService;

    @Autowired
    private ISysInstitutionService institutionService;


    @PostMapping("/auth/client/token")
    public ResponseEntity getClientTokenInfo() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        try {
            String clientId = request.getHeader("client_id");
            String clientSecret = request.getHeader("client_secret");
            OAuth2AccessToken oAuth2AccessToken = sysTokenService.getClientTokenInfo(clientId, clientSecret);
            if (StringUtil.isEmpty(clientId)) {
                clientId = "webApp";
                clientSecret = "webApp";
            }

            return ResponseEntity.succeedWith(oAuth2AccessToken, UaaConstant.AUTH_CODE_SUCCESS, "操作成功");
        } catch (InvalidGrantException e) {
            return ResponseEntity.of(UaaConstant.AUTH_USERORPASSWORD_ILLEGAL, e.getMessage(), null);
        } catch (InternalAuthenticationServiceException e) {
            return ResponseEntity.of(UaaConstant.AUTH_USERORPASSWORD_ILLEGAL, "用户名或密码错误", null);
        }
    }

    @PostMapping("/auth/user/token")
    public ResponseEntity getUserTokenInfo(@RequestBody UserPasswordLoginRequest loginRequest) {

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        try {
            String clientId = request.getHeader("client_id");
            String clientSecret = request.getHeader("client_secret");
            if (StringUtil.isEmpty(clientId)) {
                clientId = "webApp";
                clientSecret = "webApp";
            }
            OAuth2AccessToken oAuth2AccessToken = sysTokenService.getUserTokenInfo(clientId, clientSecret, loginRequest.getUsername(), loginRequest.getPassword());

            return ResponseEntity.succeedWith(oAuth2AccessToken, UaaConstant.AUTH_CODE_SUCCESS, "操作成功");
        } catch (InvalidGrantException e) {
            return ResponseEntity.of(UaaConstant.AUTH_USERORPASSWORD_ILLEGAL, e.getMessage(), null);
        } catch (InternalAuthenticationServiceException e) {
            // 判断机构注册账号
            try {
                institutionService.findByAccount(loginRequest.getUsername(), loginRequest.getPassword(), true);
            } catch (BusinessException exception) {
                if (exception.getCode().equals(ExceptionEnum.LOGIN_AUTHING.getCode())) { //审核中
                    LoginResponse r = new LoginResponse();
                    r.setState(ExceptionEnum.LOGIN_AUTHING.getCode());
                    r.setMsg(ExceptionEnum.LOGIN_AUTHING.getMsg());
                    return ResponseEntity.succeed(r);
                }
                if (exception.getCode().equals(ExceptionEnum.LOGIN_REJECT.getCode())) {   //已驳回
                    LoginResponse r = new LoginResponse();
                    r.setState(ExceptionEnum.LOGIN_REJECT.getCode());
                    r.setMsg(ExceptionEnum.LOGIN_REJECT.getMsg());
                    return ResponseEntity.succeed(r);
                }
            }
            return ResponseEntity.of(UaaConstant.AUTH_USERORPASSWORD_ILLEGAL, "用户名或密码错误", null);
        }
    }


    @PostMapping("/auth/remove/token")
    public ResponseEntity removeToken(HttpServletRequest request) {
        Assert.notNull(tokenStore, "tokenStore must be set");
        String token = request.getParameter(CommonConstant.TOKEN);
        if (StrUtil.isEmpty(token)) {
            token = AuthUtils.extractToken(request);
        }
        if (StrUtil.isEmpty(token)) {
            return ResponseEntity.of(UaaConstant.AUTH_CODE_INVALID_TOKEN, "无效的access_token", null);
        }
        try {
            if (securityProperties.getAuth().getUnifiedLogout()) {
                OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token);
                if (oAuth2Authentication == null) {
                    return ResponseEntity.of(UaaConstant.AUTH_CODE_INVALID_TOKEN, "无效的access_token", null);
                }
                UsernameHolder.setContext(oAuth2Authentication.getName());
            }

            OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token);
            OAuth2RefreshToken refreshToken;
            if (existingAccessToken != null) {
                if (existingAccessToken.getRefreshToken() != null) {
                    log.info("remove refreshToken!", existingAccessToken.getRefreshToken());
                    refreshToken = existingAccessToken.getRefreshToken();
                    tokenStore.removeRefreshToken(refreshToken);
                }
                log.info("remove existingAccessToken!", existingAccessToken);
                tokenStore.removeAccessToken(existingAccessToken);
            }
            return ResponseEntity.succeed("登出成功");
        } catch (Exception e) {
            return ResponseEntity.failed("登出失败");
        }
    }

    @PostMapping(value = "/oauth/get/token", params = "access_token")
    public OAuth2AccessToken getTokenInfo(String access_token) {
        return sysTokenService.getTokenInfo(access_token);

    }

    /**
     * 当前登陆用户信息
     * security获取当前登录用户的方法是SecurityContextHolder.getContext().getAuthentication()
     * 这里的实现类是org.springframework.security.oauth2.provider.OAuth2Authentication
     *
     * @return
     */
    @GetMapping(value = {"/oauth/userinfo"}, produces = "application/json") // 获取用户信息。/auth/user
    public Map<String, Object> getCurrentUserDetail(HttpServletRequest request) {
        Map<String, Object> userInfo = new HashMap<>();
        try {
            BaseUser sysUser = UserUtils.getCurrentUser(request, false);
            userInfo.put(CommonConstant.STATUS, CommonConstant.SUCCESS);
            LoginAppUser loginUser = AuthUtils.getLoginAppUser();
            userInfo.put("user", loginUser);
            userInfo.put("username", loginUser.getUsername());
            userInfo.put("permissions", loginUser.getPermissions());
        } catch (Exception e) {
        }
        return userInfo;

    }


    /**
     * 授权码模式特例-创建code
     */
    @RequestMapping(value = "/auth/authorize")
    public ResponseEntity authorize(@RequestParam Map<String, String> parameters,
                                    SessionStatus sessionStatus, Principal principal) {

        Map<String, String> dataMap = new HashMap<>(16);
        try {
            String clientId = parameters.get("client_id");
            String redirectUri = String.valueOf(parameters.get("redirect_uri"));
            String scope = parameters.get("scope");
            String state = String.valueOf(parameters.get("state"));
            // 支持token不透传模式
            String accessToken = parameters.get("token");
            if (StringUtil.isEmpty(clientId)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATECLIENTID, "缺失client_id");
            }
            if (StringUtil.isEmpty(scope)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失scope");
            }
            if ((principal == null || !(principal instanceof Authentication) ||
                    !((Authentication) principal).isAuthenticated()) && StringUtil.isNotEmpty(accessToken)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATEUSER, "用户未授权");
            }
            //通过ClientDetailsService获取客户端详细信息-ClientDetails对象,其中，ClientDetailsService对象在抽象类中已经完成了初始化
            //SysClient client = sysClientService.getSysClientByClientId(clientId);
            RedisClientDetailsService clientDetailsService = SpringUtil.getBean(RedisClientDetailsService.class);

            ClientDetails client = null;
            try {
                client = clientDetailsService.loadClientByClientId(clientId);
            } catch (Exception e) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_UNAUTHCLIENT, "应用未注册");
            }
            // 暂时不校验，采用了返回code模式，并未采用302重定向
//            if (StringUtil.isEmpty(redirectUri) || (client.getRegisteredRedirectUri() == null) || (!client.getRegisteredRedirectUri().contains(redirectUri))) {
//                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_ERROR_URL, "redirect_url不正确");
//            }
            if (!validateScope(scope, client.getScope())) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SCOPE, "非法的scope");
            }
            Authentication authentication = null;
            if (StringUtil.isEmpty(accessToken)) {
                authentication = SecurityContextHolder.getContext().getAuthentication();
            } else {
                OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken);
                authentication = auth2Authentication.getUserAuthentication();
            }
            Set<String> scopeSet = new HashSet<String>();
            //to-do
            String[] scopeArray = scope.split(",");
            for (String sc : scopeArray) {
                scopeSet.add(sc);
            }
            Set<String> responseTypeSet = new HashSet<String>();
            responseTypeSet.add("code");
//            Map<String, Serializable> extensionProperties = new ConcurrentHashMap<>(16);
//            if (parameters.containsKey("state")) {
//                extensionProperties.put("state", parameters.get("state"));
//            }
            //  storedRequest = storedRequest.createOAuth2Request(parameters);\
            storedRequest = new OAuth2Request(
                    parameters
                    , clientId
                    , authentication.getAuthorities() //Collection<? extends GrantedAuthority > authorities
                    , false // boolean approved
                    , scopeSet  // Set<String> scope,
                    , null  // Set<String> resourceIds
                    , String.valueOf(parameters.get("redirect_uri")) //String redirectUri,
                    , null // Set<String> responseTypes,
                    , null //Map<String, Serializable > extensionProperties
            );
            OAuth2Authentication combinedAuth = new OAuth2Authentication(storedRequest, authentication);
            String code = redisAuthorizationCodeService.createAuthorizationCode(combinedAuth);
            if (parameters.containsKey("state")) {
                dataMap.put("state", state);
            }
            dataMap.put("code", code);
            return ResponseEntity.succeedWith(dataMap, UaaConstant.AUTH_CODE_SUCCESS, "操作成功");
        } catch (Exception e) {
            log.error("获取code失败 >>>>" + e.getMessage());
            return ResponseEntity.failedWith(dataMap, UaaConstant.AUTH_CODE_FAILE, "未知错误，请联系管理员");
        }
    }

    /**
     * 校验scope
     */
    private Boolean validateScope(String requestScopes, Set<String> clientScopes) {
        if (StringUtil.isEmpty(requestScopes)) {
            return Boolean.FALSE;
        }
        String[] reqScope = requestScopes.split(",");
        for (int i = 0; i < reqScope.length; i++) {
            String scope = reqScope[i];
            if (!clientScopes.contains(scope)) {
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 创建token
     *
     * @param parameters
     * @return
     */
    @PostMapping(value = "/auth/token")
    public ResponseEntity createToken(@RequestParam Map<String, String> params) {
        try {
            String clientId = MapUtils.getString(params, "client_id");
            //String clientSecret = "thirdApplication"; // 前端不传递 后端默认一个值
            String grantType = MapUtils.getString(params, "grant_type");
            String code = MapUtils.getString(params, "code");
            String sign = MapUtils.getString(params, "sign");
            // 校验数据完整性
            if (StringUtil.isEmpty(clientId)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATECLIENTID, "缺失client_id");
            }
            if (StringUtil.isEmpty(grantType)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失grant_type");
            }
            if (!AUTHORIZATION_CODE.equals(grantType)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATE_GRANTTYPE, "非法的grant_type");
            }
            if (StringUtil.isEmpty(code)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失code");
            }
            if (securityProperties.getAuth().getValidateSign() && StringUtil.isEmpty(sign)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失sign");
            }
            DefaultClientDetails sysClient = (DefaultClientDetails) redisTemplate.opsForValue().get(SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId);

            if (sysClient == null) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_UNAUTHCLIENT, "应用未注册");
            }

            Map<String, String> newParam = new HashMap<>();
            newParam.put("client_id", clientId);
            newParam.put("grant_type", grantType);
            newParam.put("code", code);
            String sortParams = JSONObject.toJSONString(newParam, SerializerFeature.WriteMapNullValue, SerializerFeature.MapSortField);

            if (securityProperties.getAuth().getValidateSign()) {
                // 验证签名
                String descryptSign = sign;
                String publicKey = sysClient.getPublicKey();
                try {
                    if (!StringUtil.isEmpty(publicKey)) {
                        descryptSign = RsaTools.descrypt(publicKey, sign);
                    }
                    if (!descryptSign.equals(RsaTools.md5(sortParams).toUpperCase())) {
                        return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SIGN, "非法的签名");
                    }
                } catch (Exception e) {
                    log.error("sign校验错误>>>>>>" + e.getMessage());
                    return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SIGN, "非法的签名");
                }
            }
            // 校验数据一致性
//            Set<String> registeredRedirectUris = sysClient.getRegisteredRedirectUri();
//            if (registeredRedirectUris == null || registeredRedirectUris.size() == 0) {
//                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_ERROR_URL, "redirect_url不正确");
//            }
            OAuth2Authentication storedAuth = null;
            try {
                storedAuth = this.redisAuthorizationCodeService.consumeAuthorizationCode(code);
            } catch (InvalidGrantException e) {
                log.error("获取token失败>>>>>", e);
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_ERROR_CODE, "code错误或已失效");
            }
            if (storedAuth == null) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_ERROR_CODE, "code错误或已失效");
            } else {
                OAuth2Request pendingOAuth2Request = storedAuth.getOAuth2Request();
//                String redirectUriApprovalParameter = (String) pendingOAuth2Request.getRequestParameters().get("redirect_uri");

//                if (!registeredRedirectUris.contains(redirectUriApprovalParameter)) {
//                    return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_ERROR_URL, "redirect_url不正确");
//                } else {
                String pendingClientId = pendingOAuth2Request.getClientId();
                if (!clientId.equals(pendingClientId)) {
                    return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_NOT_MATCH_CODE, "client_id不匹配");
                } else {
                    // 创建token
                    Map<String, String> combinedParameters = new HashMap(pendingOAuth2Request.getRequestParameters());
                    combinedParameters.putAll(params);
                    OAuth2Request finalStoredOAuth2Request = pendingOAuth2Request.createOAuth2Request(combinedParameters);
                    Authentication userAuth = storedAuth.getUserAuthentication();
                    OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(finalStoredOAuth2Request, userAuth);
                    oAuth2Authentication.setAuthenticated(true);

                    DefaultTokenServices myTokenService = new CustomTokenServices(securityProperties.getAuth());
                    myTokenService.setSupportRefreshToken(true);
                    myTokenService.setTokenStore(tokenStore);
                    myTokenService.setTokenEnhancer(tokenEnhancer);
                    OAuth2AccessToken accessToken = myTokenService.createAccessToken(oAuth2Authentication);
                    return ResponseEntity.succeedWith(accessToken, UaaConstant.AUTH_CODE_SUCCESS, "请求成功");
                }
//                }
            }
        } catch (Exception e) {
            log.error("获取token失败>>>>>", e);
            return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_FAILE, "未知错误，请联系管理员");
        }
    }

    /**
     * 刷新token
     *
     * @param params {"grant_type":"refresh_token","refresh_token":"304f8cb3-d2eb-44e7-9dfc-b57bddf7048f",
     *               "client_id":"testxh","sign":grant_type + refresh_token + client_id md5加密}
     * @return
     */
    @PostMapping("/auth/refresh/token")
    public ResponseEntity refreshTokenCode(@RequestParam Map<String, Object> params) {
        Map<String, Object> data = new HashMap<>(); //自定义返回值
        try {
            String grantType = MapUtils.getString(params, "grant_type");
            String refresh_token = MapUtils.getString(params, "refresh_token");
            String clientId = MapUtils.getString(params, "client_id");
//			String scope = MapUtils.getString(params, "scope");
            String sign = MapUtils.getString(params, "sign");
            Set<String> scopeSet = null;
//			if (Tools.notEmpty(scope)) {
//				scopeSet = Arrays.stream(scope.split(",")).collect(Collectors.toSet());
//			}
            // 校验
            if (StringUtil.isEmpty(clientId)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATECLIENTID, "缺失client_id");
            }
            if (StringUtil.isEmpty(grantType)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失grant_type");
            }
            if (!"refresh_token".equals(grantType)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATE_GRANTTYPE, "非法的grant_type");
            }
            if (StringUtil.isEmpty(refresh_token)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_REFRESH_EMPTY, "缺失refresh_token");
            }
            if (securityProperties.getAuth().getValidateSign() && StringUtil.isEmpty(sign)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失sign");
            }
            OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refresh_token);
            if (refreshToken == null) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_REFRESH_ILLEGAL, "refresh_token非法");
            }
            DefaultClientDetails clientDetails = (DefaultClientDetails) redisTemplate.opsForValue().get(SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId);
            if (clientDetails == null) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_NOT_MATCH_CODE, "client_id非法");
            }
            scopeSet = clientDetails.getScope();
            Map<String, String> map = new HashMap<>();
            map.put("grant_type", grantType);
            map.put("refresh_token", refresh_token);
            TokenRequest tokenRequest = new TokenRequest(map, clientId, scopeSet, grantType);
            OAuth2Authentication oAuth2Authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken);
            String refreshClientId = oAuth2Authentication.getOAuth2Request().getClientId();
            if (!clientId.equals(refreshClientId)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_NOT_MATCH_CODE, "client_id不匹配");
            }

            Map<String, String> newParam = new HashMap<>();
            newParam.put("client_id", clientId);
            newParam.put("grant_type", grantType);
            newParam.put("refresh_token", refresh_token);
            String sortParams = JSONObject.toJSONString(newParam, SerializerFeature.WriteMapNullValue, SerializerFeature.MapSortField);

            if (securityProperties.getAuth().getValidateSign()) {
                // 验证签名
                String descryptSign = sign;
                String publicKey = clientDetails.getPublicKey();
                try {
                    if (!StringUtil.isEmpty(publicKey)) {
                        descryptSign = RsaTools.descrypt(publicKey, sign);
                    }
                    if (!descryptSign.equals(RsaTools.md5(sortParams).toUpperCase())) {
                        return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SIGN, "非法的签名");
                    }
                } catch (Exception e) {
                    log.error("sign校验错误>>>>>>" + e.getMessage());
                    return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SIGN, "非法的签名");
                }
            }

            //自定义token逻辑 todo
            DefaultTokenServices myTokenService = new CustomTokenServices(securityProperties.getAuth());
            myTokenService.setSupportRefreshToken(true);
            myTokenService.setTokenStore(tokenStore);
            myTokenService.setTokenEnhancer(tokenEnhancer);
            OAuth2AccessToken oAuth2AccessToken = myTokenService.refreshAccessToken(refresh_token, tokenRequest);
            data.put("access_token", oAuth2AccessToken.getValue());
            data.put("token_type", oAuth2AccessToken.getTokenType());
            data.put("refresh_token", oAuth2AccessToken.getRefreshToken().getValue());
            data.put("expires_in", oAuth2AccessToken.getExpiresIn());
            data.put("scope", String.join(",", oAuth2AccessToken.getScope()));
//			LoginAppUser loginAppUser = (LoginAppUser) oAuth2Authentication.getPrincipal();
//			data.put("skin", loginAppUser.getByzd1()); //主题
            oAuth2Authentication.setAuthenticated(true);
            return ResponseEntity.succeedWith(data, UaaConstant.AUTH_CODE_SUCCESS, "操作成功");
        } catch (InvalidTokenException e) {
            log.error(e.toString(), e);
            return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_REFRESH_EXPIRED, "refresh token过期");
        } catch (Exception e) {
            log.error(e.toString(), e);
            log.error("create refresh_token error");
            return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_FAILE, e.getMessage());
        }
    }

    /**
     * 从token获取用户信息
     *
     * @param params
     * @return
     */
    @PostMapping("/auth/userInfo")
    public ResponseEntity userInfo(@RequestParam Map<String, Object> params, HttpServletRequest request) {
        try {
            // 校验参数
            String clientId = MapUtils.getString(params, "client_id");
            String authToken = request.getHeader("Authorization").replaceFirst(BEARER_TYPE, "").trim();
            String sign = MapUtils.getString(params, "sign");
            if (StringUtil.isEmpty(clientId)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALIDATECLIENTID, "缺失client_id");
            }
            if (StringUtil.isEmpty(authToken)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_TOKEN, "无效的access_token");
            }
            if (securityProperties.getAuth().getValidateSign() && StringUtil.isEmpty(sign)) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_PARAMETER, "缺失sign");
            }
            DefaultClientDetails clientDetails = (DefaultClientDetails) redisTemplate.opsForValue().get(SecurityConstants.CACHE_CLIENT_KEY + ":" + clientId);
            if (clientDetails == null) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_UNAUTHCLIENT, "应用未注册");
            }

            Map<String, String> newParam = new HashMap<>(2);
            newParam.put("auth_token", authToken);
            newParam.put("client_id", clientId);
            String sortParams = JSONObject.toJSONString(newParam, SerializerFeature.WriteMapNullValue, SerializerFeature.MapSortField);
            if (securityProperties.getAuth().getValidateSign()) {
                // 验证签名
                String descryptSign = sign;
                String publicKey = clientDetails.getPublicKey();
                try {
                    if (!StringUtil.isEmpty(publicKey)) {
                        descryptSign = RsaTools.descrypt(publicKey, sign);
                    }
                    if (!descryptSign.equals(RsaTools.md5(sortParams).toUpperCase())) {
                        return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SIGN, "非法的签名");
                    }
                } catch (Exception e) {
                    log.error("sign校验错误>>>>>>" + e.getMessage());
                    return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_SIGN, "非法的签名");
                }
            }

            // 获取用户信息
            OAuth2Authentication authentication = tokenStore.readAuthentication(authToken);
            if (authentication == null) {
                return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_INVALID_TOKEN, "非法的token");
            }
            LoginAppUser principal = (LoginAppUser) authentication.getUserAuthentication().getPrincipal();
            Map<String, Object> data = new HashMap<>();
            Set<String> clientScope = authentication.getOAuth2Request().getScope();

            data.put("username", principal.getUsername());
            data.put("realname", principal.getRealname());
            data.put("mobile", principal.getMobile());
            data.put("Organization", principal.getOrganizationId());
            data.put("headImgUrl", principal.getHeadImgUrl());

            // token续约 -todo
            OAuth2AccessToken accessToken = tokenStore.readAccessToken(authToken);
            tokenStore.readAuthentication(accessToken);
            return ResponseEntity.succeedWith(data, UaaConstant.AUTH_CODE_SUCCESS, "请求成功");
        } catch (Exception e) {
            log.error("获取用户信息异常>>>>>>>", e);
            return ResponseEntity.failedWith(Collections.emptyMap(), UaaConstant.AUTH_CODE_FAILE, "未知错误，请联系管理员");
        }
    }

    /**
     * 获取秘钥对
     */
    @GetMapping(value = "/auth/getKeyPair")
    public ResponseEntity getKeyPair() throws BusinessException {
        Map dataMap = new HashMap(16);
        try {
            String[] arr = ConfigTools.genKeyPair(512);
            String privateKey = arr[0];
            String publicKey = arr[1];
            dataMap.put("privateKey", privateKey);
            dataMap.put("publicKey", publicKey);
        } catch (Exception e) {
            log.error("生成秘钥对失败," + e.getMessage());
            return ResponseEntity.failed(dataMap, "操作失败");
        }
        return ResponseEntity.succeed(dataMap, "操作成功");
    }

    /**
     * 获取webApp应用签名
     */
    @GetMapping(value = "/auth/getSign")
    public ResponseEntity getSign(@RequestParam(value = "refresh_token") String refresh_token) {
        try {
            DefaultClientDetails clientDetails = (DefaultClientDetails) redisTemplate.opsForValue().get(SecurityConstants.CACHE_CLIENT_KEY + ":" + "webApp");
            String privatekey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAyzUoCwfFnZoZWFgL/e8o5x5MXg6FIcs1DTncmHGAjwrrLsGGkNPFiaL+jb0EG145qvGQ9TSmXJZdhTfjkTAO9QIDAQABAkBaW/rAXOZc3Gckx5IdirlvfCONN3uvuUKP7QjQqLf34qIgYJvhm7Wn7ePIhcw41pxo/V/dzUCzEEGmDgDcsYMJAiEA6r0EadUks1Fw7LzQFCc3zqcm1Ke8ikkP/zPv9MiyoPMCIQDdnQXLI99bjmlPO/Xfm9uY/yxTGxavMo+n//BcLhtKdwIgDhDLbegGrfQIVzctJLgA4RIlAoMWiha8racYDsvj4D8CIQCUyhUWs2oGDZJ06TwGOp1wlnpK/df4HslGsVbOfQJDtwIgLoSsA5X0YJw/+8rrbA1mdOFQUaSNVcZK6iFwXG7N4xM=";
            String sign = "";

            Map<String, String> dataMap = new HashMap<>();
            dataMap.put("client_id", "webApp");
            dataMap.put("grant_type", "refresh_token");
            dataMap.put("refresh_token", refresh_token);

            return ResponseEntity.succeed(RsaTools.getRsaSign(clientService.loadClientByClientId("webApp", "").getPrivateKey(), dataMap));
        } catch (Exception e) {
            return ResponseEntity.failed("获取失败");
        }
    }

}
